using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using System.Threading;
using System.Reflection;

namespace HubertTestProgram
{
    public class Brain 
    {
        #region BrainProcesses
        private Movement movement;
        private DetectMovingPerson detectMovingPerson;
        private TextToSpeechBrainProcess textToSpeechBrainProcess;
        #endregion

        #region Other fields
        private System.Diagnostics.Stopwatch stopWatch;
        private double utilityFunctionUpdateInterval;
        private double brainStepThreadSleepInterval;
        private System.Diagnostics.Stopwatch elapsedTimeWatch;
        private Thread brainStepThread;
        private bool running;
        #endregion

        #region Constructors 
        public Brain()
        {
            movement = new Movement();
            detectMovingPerson = new DetectMovingPerson();
            textToSpeechBrainProcess = new TextToSpeechBrainProcess();
            stopWatch = new System.Diagnostics.Stopwatch();
            elapsedTimeWatch = new System.Diagnostics.Stopwatch();
        }
        #endregion

        #region Private methods

        private void BrainStepLoop()
        {
            while (running)
            {
                Thread.Sleep( (int)(brainStepThreadSleepInterval*1000) );
                Step();
            }
        }

        private void Step()
        {
            double dt = ((double)stopWatch.ElapsedMilliseconds) / 1000.0;
            if (dt >= utilityFunctionUpdateInterval)
            {
                movement.SetActivityState();
                detectMovingPerson.SetActivityState();
                textToSpeechBrainProcess.SetActivityState();
                stopWatch.Reset();
                stopWatch.Start();
            }
        }

        #endregion

        #region Public Methods

        public void Initialize()
        {
            // Initialize brain processes here:
            movement.Initialize();
            detectMovingPerson.Initialize();
            textToSpeechBrainProcess.Initialize();
            elapsedTimeWatch.Reset();
        }

        public void Start()
        {
            running = true;
            stopWatch.Reset();
            stopWatch.Start();
            elapsedTimeWatch.Start();
            brainStepThread = new Thread(BrainStepLoop);
            brainStepThread.Start();
        }

        public void Stop()
        {
            running = false;
            brainStepThread.Join();
            stopWatch.Stop();
            elapsedTimeWatch.Stop();
        }
        #endregion

        #region Properties 
        public long ElapsedTime
        {
            get { return elapsedTimeWatch.ElapsedMilliseconds; }
        }
        public double UtilityFunctionUpdateInterval
        {
            get { return utilityFunctionUpdateInterval; }
            set { utilityFunctionUpdateInterval = value; }
        }
        public double BrainStepThreadSleepInterval
        {
            get { return brainStepThreadSleepInterval; }
            set { brainStepThreadSleepInterval = value; }
        }
        #endregion

        #region Brain process properties
        public Movement Movement
        {
            get { return movement; }
        }
        public DetectMovingPerson DetectMovingPerson
        {
            get { return detectMovingPerson; }
        }
        public TextToSpeechBrainProcess TextToSpeechBrainProcess
        {
            get { return textToSpeechBrainProcess; }
        }
        #endregion

    }
}